/***
	GradientView by J. Shan Bell
	Nov 7, 1993
	v1.1

	There are no restrictions on this code, it's in the public domain.  I accept
	no responsibility for it's fitness for any particular use.
***/


#import "GradientView.h"
#import "Thinker.h"
#import <math.h>
#import <libc.h>
#import <dpsclient/wraps.h>

#define STEPS  256   /* number of gradation steps */
#define LEN    256   /* length of a string, as in the default database strings */

@implementation GradientView

- initFrame:(const NXRect *)rect
{
	[super initFrame: rect];

	topColor = NX_COLORBLUE;
	bottomColor = NXChangeBrightnessComponent(NX_COLORBLUE, 0.1);

	[self readTopColor: self];
	[self readBottomColor: self];

	aColorWellHasChanged = YES;
	doingScreenSaver = NO;

	return self;
}

- oneStep
{
	usleep(1000000 * 1/2 );			//sleep a while (yuck!)
	// this time should be short enough that BackSpace remains
	// somewhat responsive if an event does occur.  Unfortunately,
	// waking up keeps BackSpace hotter than I would prefer (ie paged in)

	return self;
}

- drawSelf:(const NXRect *)rects :(int)rectCount
{
	static int i;
	static float stepWidth;
	static NXRect fillArea;
	static NXColor currentFill;
	static float redInc, greenInc, blueInc;
	static float redValue, greenValue, blueValue;

	/* if we're in screen saver mode, then just black out the screen */

	if (doingScreenSaver)
	{
		PSsetgray(NX_BLACK);
		NXRectFill(&bounds);
		return self;  /* don't do anything, leave it black */
	}

	/* We're doing the gradient, calculate the width of each step */

	stepWidth = bounds.size.height/STEPS;
	bcopy(&bounds, &fillArea, sizeof(NXRect));
	fillArea.size.height = stepWidth;

	bcopy(&bottomColor, &currentFill, sizeof(NXColor));

	/* We're going to do a linear interpolation between each component */

	redValue = NXRedComponent(currentFill);
	greenValue = NXGreenComponent(currentFill);
	blueValue = NXBlueComponent(currentFill);

	if (aColorWellHasChanged)
	{
		/* Calculate the increment value, this has only change if the color wells changed */

		redInc = (NXRedComponent(topColor) - redValue)/STEPS;
		greenInc = (NXGreenComponent(topColor) - greenValue)/STEPS;
		blueInc = (NXBlueComponent(topColor) - blueValue)/STEPS;

		aColorWellHasChanged = NO;
	}

	for (i = 0; i < STEPS; i++)
	{
		NXSetColor(currentFill);
		NXRectFill(&fillArea);
		fillArea.origin.y = stepWidth*(i + 1);
		redValue += redInc;
		greenValue += greenInc;
		blueValue += blueInc;
		currentFill = NXChangeRedComponent(currentFill, redValue);
		currentFill = NXChangeGreenComponent(currentFill, greenValue);
		currentFill = NXChangeBlueComponent(currentFill, blueValue);
	}

	return self;
}

- (BOOL)isBoringScreenSaver
{
	return YES;
}

- getBottomColor: sender
{
	bottomColor = [bottomColorWell color];

	return self;
}

- getTopColor: sender
{
	topColor = [topColorWell color];

	return self;
}

- apply: sender
{
	aColorWellHasChanged = YES;

	[self getBottomColor: self];
	[self getTopColor: self];

	[self writeColors: self];

	[self update];

	return self;
}

- inspector: sender
{
	char buf[MAXPATHLEN];

	if (!inspectorPanel)
	{
		sprintf(buf, "%s/gradient.nib", [sender moduleDirectory: "Gradient"]);
		[NXApp loadNibFile: buf owner: self withNames: NO];

		[topColorWell setColor: topColor];
		[bottomColorWell setColor: bottomColor];
	}

	return inspectorPanel;
}

- (BOOL) useBufferedWindow
{
	return YES;
}

- writeColors: sender
{
	[self writeTopColor: self];
	[self writeBottomColor: self];

	return self;
}

- writeTopColor: sender
{
	static char str[LEN];

	sprintf(str, "%1.5f %1.5f %1.5f",
	        NXRedComponent(topColor),
			NXGreenComponent(topColor),
			NXBlueComponent(topColor));

	NXWriteDefault([NXApp appName], "Gradient top color", str);

	return self;
}

- readTopColor: sender
{
	static const char *str;
	static float r,g,b;

	if ((str = NXReadDefault([NXApp appName], "Gradient top color")) == NULL)
		return nil;

	if (sscanf(str, "%f%f%f", &r, &g, &b) != 3)
	{
		NXLogError("Could not read default for top color.\n");
		return nil;
	}

	topColor = NXChangeRedComponent(topColor, r);
	topColor = NXChangeGreenComponent(topColor, g);
	topColor = NXChangeBlueComponent(topColor, b);

	return self;
}

- writeBottomColor: sender
{
	static char str[LEN];

	sprintf(str, "%1.5f %1.5f %1.5f",
	        NXRedComponent(bottomColor),
			NXGreenComponent(bottomColor),
			NXBlueComponent(bottomColor));

	NXWriteDefault([NXApp appName], "Gradient bottom color", str);

	return self;
}

- readBottomColor: sender
{
	static const char *str;
	static float r,g,b;

	if ((str = NXReadDefault([NXApp appName], "Gradient bottom color")) == NULL)
		return nil;

	if (sscanf(str, "%f%f%f", &r, &g, &b) != 3)
	{
		NXLogError("Could not read default for bottom color.\n");
		return nil;
	}

	bottomColor = NXChangeRedComponent(bottomColor, r);
	bottomColor = NXChangeGreenComponent(bottomColor, g);
	bottomColor = NXChangeBlueComponent(bottomColor, b);

	return self;
}

- enteredScreenSaverMode
{
	doingScreenSaver = YES;
	[self update];

	return self;
}

- willExitScreenSaverMode
{
	doingScreenSaver = NO;
	[self update];

	return self;
}

@end
